// // const cache = {}
// // function fn(n){
// //     if(n < 3) return n;
// //     // if(cache[n]) return cache[n]
// //     // cache[n] = fn(n-1) + fn(n-2);
// //     // return cache[n]
// //     return fn(n-1) + fn(n-2);
// // }



// // function fn2(n){
// //     if(n < 3) return n;
// //     let cur = 0, next = 1, cache =0;
// //     for(var i = 0; i < n; i++){
// //         cache = next;
// //         next = cur + next;
// //         cur = cache;
// //     }
// //     return next;
// // }
// // console.log(

// //     fn(15)
// // )
// // console.log(

// //     fn2(15)
// // )

// // console.log(

// //     cache
// // )


// function bubble(arr){
//     var x = 0;
//     var len = arr.length - 1;
//     for(var i = 0; i < len; i++){
//         var hasChange = false
//         for(var n = 0; n < len -i; n++){
//             x++
//             if(arr[n] > arr[n+1]){
//                 hasChange = true;
//                 [arr[n], arr[n+1]] = [arr[n+1], arr[n]]
//             }
//         }
//         if(!hasChange) break;
//     }
//     console.log(x);
//     return arr;
// }

// console.log(bubble([1,5,3,2,4,7,8,9]))


// function insert(arr){
//     if(arr.length < 2) return arr;
//     var len = arr.length;
//     for(var i = 0; i < len-1; i++){
//         for(var j = i +1; j > 0; j--){
//             if(arr[j] < arr[j-1]){
//                 [arr[j], arr[j-1]] = [arr[j-1], arr[j]]
//             }else{
//                 break;
//             }
//         }
//     }
//     return arr;
// }

// console.log(insert([1,5,3,2,4,7,8,9]))

// function select(arr){
//     if(arr.length < 2) return arr;
//     var len = arr.length;
//     for(var i = 0; i < len; i++){
//         var min = i;
//         for(var j = i+1; j < len; j++){
//             if(arr[j] < arr[min]){
//                 min = j
//             }
//         }
//         [arr[i], arr[min]] = [arr[min], arr[i]]
//     }
//     return arr;
// }

// console.log(select([1,5,3,2,4,7,8,9]))


// // 归并

// function sort(arr){
//     var len = arr.length;
//     if(len <　2) return arr;

//     var mid = Math.floor(len/2),
//         left = arr.slice(0, mid),
//         right = arr.slice(mid);


//     return merge(sort(left), sort(right))
// }

// function merge(left, right){
//     const result = []
//     // 最小单元  1 * 1  => 排序后的[1,1]
//     // 往上是排序后的 [x, x2,...] 与 [y1, y2, ...]
//     while(left.length && right.length){
//         if(left[0] <= right[0]){
//             result.push(left.shift());
//         }else{
//             result.push(right.shift())
//         }
//     }
//     return result.concat(left, right)
// }


// console.log(sort([1,5,3,2,4,7,8,9]))


// // 快排 找一个点 分左右

// function quick(arr){
//     var len = arr.length;
//     if(len <　2) return arr;

//     var base = arr[0], left = [], right = [];
//     for(var i = 1; i < len; i++){
//         if(arr[i] <= base){
//             left.push(arr[i])
//         }else{
//             right.push(arr[i])
//         }
//     }
//     return quick(left).concat(base, quick(right))
// }

// console.log('-----------')
// console.log(quick([1,5,3,2,4,7,8,9]))




// function mergeSort(arr){
//     // 栈层级一层一层的
//     function sort(arr, first, last){
//         if(last - first < 1){ // 递归到 sort(arr, 1, 1) 其实就是 arr[1]
//             return;
//         }  // 递归结束 停止条件，开始归并结果
//         var mid = Math.floor((first+last)/2);  
//         sort(arr, first, mid);  // 递归拆分  // 1,5,3,2 -> 3,2 ->3/2 <-2 <-3 
//         sort(arr, mid+1, last);

//         // 当一个的返回来后 处理 多个的问题， 这时候处理的是 first -> last的范围
//         // 这的最小处理2个 比如 first = 3 last = 4 mid = 3;

//         // 处理回来的排序问题
//         var i = first, m = mid, j = mid +1, re = [];
//         // 这后面 就是2个合并的区间排序问题 为了不增加空间消耗 要做原地排序

//         // 1.这样空间复杂度就是 O(n) n个合并元素
//         while(i <= m && j <= last){     
//             if(arr[i] <= arr[j]){
//                 re.push(arr[i++]);
//             }else{
//                 re.push(arr[j++]);
//             }
//         }
//         // 剩下的都放在数组尾部 如果是i < m 那么左边的剩下了 如果是 j < last 那么就是右边剩下了

//         while(i<=m){
//             re.push(arr[i++])
//         }
//         while(j <= last){
//             re.push(arr[j++])
//         }
//         // return re; // 这样不行， 原素组没改
//         // 元数组区域覆盖
//         for(var x = 0; x < re.length; x++){
//             arr[first+x] = re[x];
//         }

//         return arr
//     }

//     return sort(arr, 0, arr.length -1);
// }


// console.log('-----------')
// console.log(mergeSort([1,5,3,2,4,7,8,9]))


// // quick(p..r) = quick(p..q-1) + quick(q+1...r)
// // 结束条件 p >=r
// function quickMerge(arr){
//     function sort(arr, start, end){
//         if(start > end) return;

//         var point = partition(arr, start, end); // 当前数组分块 左小右大

//         sort(arr, start, point -1);
//         sort(arr, point+1, end);
//     }

//     function partition(arr, start, end){  // 当前数组原地(原点)排序 不完全排序只排序大小
//         var storeIndex = start;
//         var pivot  = arr[end];
//         for(var i = start; i < end; i++){   // 插入排序 并且返回隔离点
//             if(arr[i] < pivot){
//                 [arr[storeIndex], arr[i]] = [arr[i], arr[storeIndex]]
//                 storeIndex++;
//             }
//         }
//         // 交换 i 和 index, 这样index 前面的是 小于index 后面的是大于index
//         [arr[storeIndex], arr[end]] = [arr[end], arr[storeIndex]]
//         return storeIndex;
//     }

//     sort(arr, 0, arr.length -1);
//     return arr;
// }

// console.log('-----------')
// console.log(quickMerge([1,5,3,2,4,7,8,9]))



// // 二分查找f

// function  find(arr, elm){
//     var low = 0, hight = arr.length -1;

//     while(low <= hight){
//         var mid = Math.floor((hight+low)/2);
//         if(arr[mid] == elm){
//             return mid
//         }else if( arr[mid] < elm){
//             low = mid +1;
//         }else{
//              hight = mid -1;
//         }
//     }
//     return -1;
// }


// console.log(find([1,5,3,2,4,7,8,9], 2))



// function  find2(arr, value){
//     var low = 0, hight = arr.length;
//     while(low <= hight){
//         var mid = low + ( (hight-low) >> 1);
//         if(arr[mid] > value){
//             hight = mid - 1;
//         }else if(arr[mid] < value){
//             low = mid +1;
//         }else{
//             if(mid == arr.length -1 || arr[mid+1] != value){
//                 return mid
//             }else{
//                 low = mid +1
//             }
//         }
//     }
//     return -1;
// }


// console.log(find2([1,2,3,4,6,7,8,9], 8))
// // 查找最后一个小于等于给定值的元素
// function find3(arr, value){
//     var low = 0, hight = arr.length;
//     while(low <= hight){
//         var mid = low + ((hight - low) >> 1); 
//         if(arr[mid] > value){
//             hight = mid - 1;
//         }else{
//             if(mid == 0 || arr[mid+1] > value) return mid;
//             low = mid +1;
//         }
//     }
// }
// let onWatch = (obj, setBind, getLogger) => {
//     let handler = {
//       get(target, property, receiver) {
//         getLogger(target, property)
//         return Reflect.get(target, property, receiver)
//       },
//       set(target, property, value, receiver) {
//         setBind(value, property)
//         return Reflect.set(target, property, value)
//       }
//     }
//     return new Proxy(obj, handler)
//   }
//   let onWatch = (obj, setBind, getLogger) => {

// let onWatch =(obj, getLogger, setLogger)=>{
//     let handler = {
//         get(target, property, receiver){
//             getLogger(target, property);
//             return Reflect.get(target, property, receiver)
//         },
//         set(target, property, value ,receiver){
//             setLogger(property,value);
//             return Reflect.set(obj, property, value, receiver);
//         }
//     }
//     return new Proxy(obj, handler)
// }

// let obj = {a: 1}

// var p = onWatch(obj,
//     (target, property) => {
//         console.log(`获取属性${property}的值为：${target[property]}`)
//     },
//     (property,value) => {
//         console.log(`监听到属性${property}改变为${value}`)
//     }
// )

// p.a = 2
// p.a



// function myInstanceof(obj, pro){
//     // 一直往上找，找到相等的返回true, 一直找到顶部没有返回false
//     let proto = Object.getPrototypeOf(obj);
//     let prototype = pro.prototype;

//     while(true){
//         if(!proto) return false;
//         if(proto === prototype) return true;
//         // 往上找
//         proto = Object.getPrototypeOf(proto)
//     }
// };

// // var obj = myNew(fn, args) 
// function myNew(){
//     const [fn, ...params] = arguments;
//     var obj = Object.create(fn.prototype);
//     var re = fn.apply(obj, params);
//     return typeof re == 'object' ? re : obj;
// }

// // bind
// // 返回一个新函数 这个函数能当做构造函数 这个函数使用obj作为this 
// // var newFN = fn.bind(obj, arg1, arg2,...);
// Function.prototype.bind2 = function(){
//     const fn = this;
//     const [obj, ...params] = arguments;
//     const newFn = function(...args){
//         return fn.apply(
//             this instanceof newFn ? this : obj,
//             params.concat(args)
//         )
//     };
//     newFn.prototype = Object.create(fn.prototype);
//     newFn.prototype.constructor = newFn;
//     return newFn; 
// }

// function a(){
//     const [name = '123', ...other] = arguments;
//     console.log(name);
//     console.log(other);
// }
// a();
// a(2,4,5);
// Function.prototype.call2 = function(){
//     const [obj = window, ...other] = arguments;
//     obj.fn = this;
//     console.log(other, 11111);
//     var re = obj.fn(...other);
//     delete obj.fn;
//     return re;
// };
// Function.prototype.apply2 = function(){
//     const [obj = window, ...other] = arguments;
//     obj.fn = this;
//     var re = obj.fn(other.flat(Infinity));
//     delete obj.fn;
//     return re;
// };
// function a(age){
//     console.log(this.name, age);
// }
// // a(12);
// a.apply2({name: 123}, [12,13])

// class A  {
//     static age = 2;
//     static sex = 'man';
//     constructor(name){
//         this.name = name
//     }
//     showAge(){
//         console.log(this.age)
//     }
//     showName(){
//         console.log(this.name)
//     }
// }

// var a = new A(1122)
// a.showName()
// console.log(A.prototype.constructor)

// class B extends A {
//     age = 3;
//     constructor(name){
//         super(name)
//     }
// }

// var b = new B(222)
// b.showAge()
// b.showName()

// function ajax(url, fnSuc, fnFail){
//     if(XMLHttpRequest){
//         var oAjax = new XMLHttpRequest();
//     }else{
//         var oAjax = new ActiveXObject('Microsoft.XMLHTTP')
//     }
//     oAjax.open('GET', url, true) // 异步
//     oAjax.send()
//     oAjax.setRequestHeader()
//     oAjax.onreadystatechange = function(){
//         if(oAjax.readyState === 4){
//             if(oAjax.staus >= 200 && oAjax.status < 300 || oAjax.status === 304){
//                 fnSuc && fnSus(oAjax.responseText)
//             }else{
//                 fnFail && fnFail()
//             }
//         }
//     }
// }

// // 防抖： 一段时间不触发才执行
// // fn(fn, wait) => new Fn
// function fd(fn, wait){
//     let timer;
//     return function(...params){
//         clearTimeout(tiemr);
//         timer = setTimeout(()=>{
//             fn.apply(this, params)
//         }, wait);
//     }
// }
// // 节流：每隔一段时间触发一次
// // fn(fn, wait) => newFn

// function jl(fn, wait){
//     let timer;
//     return function(...params){
//         if(timer)return;
//         timer = setTimeout(()=>{
//             fn.apply(this, params);
//             timer = null;
//         }, wait)
//     }
// }
// function fn(n, point = 1, count = 1) {
//     if (n <= 1) return count;
//     return fn(n - 1, count, point + count);
//   }

// function fn(n){
//     if(n<2) return 1;
//     return fn(n-1) + fn(n-2);
// }

// function fn(n, point =1, count = 1){
//     if(n <=1) return count;
//     return fn(n-1, count, point + count);
// }

// console.log(fn(5))


// let arr = ['a', 'b', 'c'];
// let iter = arr[Symbol.iterator]();

// console.log(iter.next());


// var a = {};
// a[Symbol.iterator] = function(){
//     let n = 1;
//     return {
//         next: ()=>{ return {value: n++, done: n > 5 ? true : false }}
//     }
// }
// for(var x of a){
//     console.log(x)
// }

// var b = [1,2,3];
// console.log(b[Symbol.iterator]().size);


// function *helloWorld(){
//     yield '1';
//     yield '2';
//     yield '3';
// }

// var val = helloWorld();
// // console.log(val[Symbol.iterator]())
// console.log(val.next())
// for(var x of val){
//     console.log(x)
// }
// function timeout(ms) {
//     return new Promise((resolve, reject) => {
//         setTimeout(resolve, ms, 'done');
//     });
// }

// var promise = timeout(100);
// var p2 = promise.then((value) => {
//     console.log(value)
//     // return 2;
//     // return Promise.resolve(2);
// });
// p2.then(value =>{
//     console.log(p2, 111)
// })
//


// TODO: promise实现

// 装饰器：
// function sayHi(target){
//     target.sayHi = () => {console.log('hi')}
// }
// @sayHi
// class Person {
//     constructor(){}
// }



// var p1 = new Person();
// p1.sayHi()

// 装饰器添加参数
// function setName(name){
//     return function(target){
//         target.name =  name;//静态属性
//         target.prototype.name = name; // 实例属性
//     }
// }
// @setName('person')
// class Person {
//     constructor(){}
// }

// // 装饰器装饰方法
// function readonly(target, name, descriptor){
//     // taget: Animal
//     // name: 'name'
//     // descriptor: {
//     //     value: specifiedFunction,
//     //     enumerable: false,
//     //     writable: true,
//     //     configurable: true
//     // }
//     descriptor.writable = false;
//     return descriptor;
// }
// function log(target, name, descriptor){
//     const oldvalue = descriptor.value; //func
//     descriptor.value = function(){
//         console.log('1111');
//         oldvalue.apply(null, arguments)
//     }
// }
// class Animal {
//     @readonly
//     @log
//     name(){
//         return `${this.first}-${this.second}`;
//     }
// }


// var add = function(a) {

//     return function (b) {
//         console.log(a, b)
//         return a + b

//     }

// }

// var add= (a) => (b) => (c) =>{
//     return a + b + c
// }

// var b = add(2);
// console.log(b.toString())
// console.log( b(1)(2));

var a = (action) => console.log(action);
var b = (action) => console.log(action,2222);

a(b)(1);
